using System;
using System.Collections;

using NetBpm.Util.Client;
using Castle.Services.Transaction;
using NHibernate;
using Castle.Facilities.NHibernateIntegration;
//using BEGDC.CC.BL;
using NetBpm.Workflow.Definition.EComp;
using NetBpm.Workflow.Definition;

namespace BEGDC.CC.BL.Workflow
{
	/// <summary>
	/// Implemente the IDefinition interface by NetBPM workflow engine
	/// </summary>
	[Transactional]
	public class NBPMDefinitionService : IDefinition
	{
		/// <summary>
		/// Constructor
		/// </summary>
		public NBPMDefinitionService(ISessionManager sessionManager)
		{
			this.sessionManager = sessionManager;
//			context = new ProjectContext();
		}

		ISessionManager sessionManager;

//		private ProjectContext context;

		private const int IQ_Index = 3;
		private const int Sample_Index = 4;
		private const int TQ_Index = 2;
		private const int VP_Index = 1;
		private const int VP_SubIndex = 1;

		//=========*BSS*=============
		private const int IQAsse_SubIndex = 8;
		private const int IQAsseRV_SubIndex = 9;
		private const int IQTest_SubIndex = 10;
		private const int IQTestRV_SubIndex = 11;
		private const int IQSumRpt_SubIndex = 13;
		private const int IQReviewRpt_SubIndex = 14;
		//=========*End of BSS*======

		#region IDefinition Members
		/// <summary>
		/// Get process definition information by specified ID
		/// </summary>
		/// <returns>Process Definition Information</returns>
		[Transaction(TransactionMode.Requires)]
		public ProcessStateList GetDefinition()
		{	
			if (!Configuration.IsSetStates)
			{
				this.SetProcessState();
			}
			return Configuration.CVProcessDefinition;
		}

		[Transaction(TransactionMode.Requires)]
		public ProcessStateList GetDefinition(string processName)
		{
			if (!Configuration.IsSetStates)
			{
				this.SetProcessState();
			}
			switch(processName)
			{
				case "CRProcess":
					return Configuration.CRProcessDefinition;
				case "CVProcess":
					return Configuration.CVProcessDefinition;
				case "EVProcess":
					return Configuration.EVProcessDefinition;
				case "OutCRProcess":
					return Configuration.OutCRProcessDefinition;
				case "APProcess":
					return Configuration.APProcessDefinition;
				default:
					return null;
			}
		}

//		/// <summary>
//		/// Get process definition information by specified ID
//		/// </summary>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetCRDefinition()
//		{
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			return Configuration.CRProcessDefinition;
//		}

//		/// <summary>
//		/// Get CCC process definition information by specified ID
//		/// </summary>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetCCCDefinition()
//		{
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			return Configuration.CCCProcessDefinition;
//		}
		
//		/// <summary>
//		/// Get TS process definition information by speficied ID
//		/// </summary>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetTSDefinition()
//		{
//			if(!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			return Configuration.TSProcessDefinition;
//		}

//		/// <summary>
//		/// 
//		/// </summary>
//		/// <param name="crID"></param>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetCRInstanceStates(int crID)
//		{
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			ProcessStateList states = (ProcessStateList)Configuration.CRProcessDefinition.Clone();
//			if (crID != 0)
//			{
//				using(ISession session = sessionManager.OpenSession())
//				{
//					try
//					{
//						Change change = session.Get(typeof(Change), crID) as Change;
//						for(int i=0; i<states.Count; i++)
//						{
//							ProcessState state = states[i];
//							for(int j=0; j<state.ChildrenStates.Count; j++)
//							{
//								if (state.ChildrenStates[j].Key == change.ChangeStatus)
//								{
//									states[i].State = ProcessStateEnum.OnGoing;
//									state.ChildrenStates[j].State = ProcessStateEnum.OnGoing;
//									break;
//								}
//							}
//						}
//					}
//					finally
//					{
//						if (session != null)
//							session.Close();
//					}					
//				}
//			}			
//			return states;
//		}
//
		
//		/// <summary>
//		/// 
//		/// </summary>
//		/// <param name="projectID"></param>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetCCCInstanceStates(int projectID)
//		{
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			ProcessStateList states = (ProcessStateList)Configuration.CCCProcessDefinition.Clone();
//			if (projectID != 0)
//			{
//				using(ISession session = sessionManager.OpenSession())
//				{
//					try
//					{
//						Project project = context.GetProject(session, projectID);
//						//Do Set Current States
//						bool is_done = true;
//						for(int i=0; i<states.Count; i++)
//						{
//							ProcessState state = states[i];
//							for(int j=0; j<state.ChildrenStates.Count; j++)
//							{
//								if (state.ChildrenStates[j].Key == project.ProjectStatus)
//								{
//									states[i].State = ProcessStateEnum.OnGoing;
//									state.ChildrenStates[j].State = ProcessStateEnum.OnGoing;
//									is_done = false;
//									break;
//								}
//								if (!is_done)
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Default;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Default;
//								}
//								else
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Finished;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Finished;
//								}
//							}
//						}
//					}
//					finally
//					{
//						if (session != null)
//							session.Close();
//					}					
//				}
//			}			
//			return states;
//		}
//

//		/// <summary>
//		/// 
//		/// </summary>
//		/// <param name="tsrecordID"></param>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProcessStateList GetTSInstanceStates(int tsrecordID)
//		{
//			if(!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//
//			ProcessStateList states = (ProcessStateList)Configuration.TSProcessDefinition.Clone();
//			if( tsrecordID != 0 )
//			{
//				using( ISession session = sessionManager.OpenSession() )
//				{
//					try
//					{
//						TSRecord record = context.GetTSRecord( session, tsrecordID );
//
//						bool isDone = true;
//						for( int i=0; i<states.Count; i++ )
//						{
//							ProcessState state = states[i];
//							for( int j=0; j<state.ChildrenStates.Count; j++)
//							{
//								if( state.ChildrenStates[j].Key == record.TSStatus )
//								{
//									states[i].State = ProcessStateEnum.OnGoing;
//									state.ChildrenStates[j].State = ProcessStateEnum.OnGoing;
//									isDone = false;
//									break;
//								}
//								if (!isDone)
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Default;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Default;
//								}
//								else
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Finished;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Finished;
//								}
//							}
//						}
//					}
//					finally
//					{
//						if( session != null )
//							session.Close();
//					}
//				}
//			}
//
//			return states;
//		}
//		

		/// <summary>
		/// Get cq process instance process states information by specified flow id
		/// </summary>
		/// <param name="flowID">flow id</param>
		/// <returns>Process states information</returns>
		[Transaction(TransactionMode.Requires)]
		public ProcessStateList GetInstanceStates(int projectID)
		{
			if (!Configuration.IsSetStates)
			{
				this.SetProcessState();
			}
			ProcessStateList states = (ProcessStateList)Configuration.CVProcessDefinition.Clone();
			if (projectID != 0)
			{
				using(ISession session = sessionManager.OpenSession())
				{
					try
					{
//						Business.Demo.DemoService service = new BEGDC.CC.BL.Demo.DemoService(sessionManager);
//						Entity.Demo demo =  service.GetDemo(projectID);
//						//Do Set Current States
//						bool is_done = true;
//						for(int i=0; i<states.Count; i++)
//						{
//							ProcessState state = states[i];
//							for(int j=0; j<state.ChildrenStates.Count; j++)
//							{
//                                if (state.ChildrenStates[j].Key == demo.DemoStatus)
//								{
//									states[i].State = ProcessStateEnum.OnGoing;
//									state.ChildrenStates[j].State = ProcessStateEnum.OnGoing;
//									is_done = false;
//									break;
//								}
//								if (!is_done)
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Default;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Default;
//								}
//								else
//								{
//									state.ChildrenStates[j].State = ProcessStateEnum.Finished;
//									if (states[i].State != ProcessStateEnum.OnGoing)
//										states[i].State = ProcessStateEnum.Finished;
//								}
//							}
//						}						
			
						//states.StatusFlag = demo.;

					}
					finally
					{
						if (session != null)
							session.Close();
					}					
				}
			}			
			return states;
		}

//		/// <summary>
//		/// 
//		/// </summary>
//		/// <param name="projectID"></param>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProjectTailor GetTailorConditions(int projectID)
//		{
//			using(ISession session = sessionManager.OpenSession())
//			{
//				try
//				{
//					return context.GetTailorConditions(session, projectID);
//				}
//				finally
//				{
//					if (session != null)
//                        session.Close();
//				}
//			}
//		}

//		/// <summary>
//		/// 
//		/// </summary>
//		/// <param name="flowID"></param>
//		/// <returns></returns>
//		[Transaction(TransactionMode.Requires)]
//		public ProjectTailor GetTailorConditions(long flowID)
//		{
//			using(ISession session = sessionManager.OpenSession())
//			{
//				try
//				{
//					return context.GetTailorConditions(session, flowID);
//				}
//				finally
//				{
//					if (session != null)
//						session.Close();
//				}
//			}
//		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns>State ID</returns>
		public long GetStateID(string stateKey)
		{
			ProcessStateList states = this.GetDefinition();
			for(int i=0; i < states.Count; i++)
			{
				ProcessState state = states[i];
				for(int j=0; j < state.ChildrenStates.Count; j++)
				{
					ProcessState chr = state.ChildrenStates[j];
					if (chr.Key == stateKey)
						return chr.ID;
				}
			}
			return -1;
		}
		#endregion

		private void SetProcessState()
		{
			Hashtable nodes = this.GetNodes(Configuration.PDAPID);			
			ProcessStateList states = Configuration.APProcessDefinition;
			for(int i=0; i<states.Count; i++)
			{
				ProcessState state = states[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes1 = this.GetNodes(Configuration.PDCRID);			
			ProcessStateList states1 = Configuration.CRProcessDefinition;
			for(int i=0; i<states1.Count; i++)
			{
				ProcessState state = states1[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes1[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes2 = this.GetNodes(Configuration.PDCVID);			
			ProcessStateList states2 = Configuration.CVProcessDefinition;
			for(int i=0; i<states2.Count; i++)
			{
				ProcessState state = states2[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes2[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes3 = this.GetNodes(Configuration.PDEVID);
			ProcessStateList states3 = Configuration.EVProcessDefinition;
			for(int i=0; i<states3.Count; i++)
			{
				ProcessState state = states3[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes3[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes4 = this.GetNodes(Configuration.PDOutCRID);
			ProcessStateList states4 = Configuration.OutCRProcessDefinition;
			for(int i=0; i<states4.Count; i++)
			{
				ProcessState state = states4[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes4[state.ChildrenStates[j].Key];
					if(flowstate != null)
						state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes5 = this.GetNodes(Configuration.PDOCVID);			
			ProcessStateList states5 = Configuration.OCVProcessDefinition;
			for(int i=0; i<states5.Count; i++)
			{
				ProcessState state = states5[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes5[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes6 = this.GetNodes(Configuration.PDOCRID);			
			ProcessStateList states6 = Configuration.OCRProcessDefinition;
			for(int i=0; i<states6.Count; i++)
			{
				ProcessState state = states6[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes6[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes7 = this.GetNodes(Configuration.PDEBDID);			
			ProcessStateList states7 = Configuration.EBDProcessDefinition;
			for(int i=0; i<states7.Count; i++)
			{
				ProcessState state = states7[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes7[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes8 = this.GetNodes(Configuration.PDESCID);			
			ProcessStateList states8 = Configuration.ESCProcessDefinition;
			for(int i=0; i<states8.Count; i++)
			{
				ProcessState state = states8[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes8[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}
			Hashtable nodes9 = this.GetNodes(Configuration.PDEBDCVID);			
			ProcessStateList states9 = Configuration.EBDCVProcessDefinition;
			for(int i=0; i<states9.Count; i++)
			{
				ProcessState state = states9[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes9[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}

			Hashtable nodes10 = this.GetNodes(Configuration.PDESCCVID);			
			ProcessStateList states10 = Configuration.ESCCVProcessDefinition;
			for(int i=0; i<states10.Count; i++)
			{
				ProcessState state = states10[i];
				for(int j=0; j<state.ChildrenStates.Count; j++)
				{
					IState flowstate = (IState)nodes10[state.ChildrenStates[j].Key];
					state.ChildrenStates[j].ID = flowstate.Id;
				}
			}
			Configuration.IsSetStates = true;
		}

		private Hashtable GetNodes(long pdID)
		{
			IDefinitionSessionLocal definitionComponent = null;
			try
			{
				definitionComponent = BEGDC.Utility.Castle.AppContainer.Instance["DefinitionSession"] as IDefinitionSessionLocal;
				IProcessDefinition def =  definitionComponent.GetProcessDefinition(pdID);				
				IEnumerator iter = def.Nodes.GetEnumerator();

				Hashtable nodes = new Hashtable();
				while (iter.MoveNext())
				{
					Type type = typeof(IState);
					if (type.IsInstanceOfType(iter.Current))
					{
						IState node = (IState)iter.Current;
						nodes.Add(node.Name, node);
					}
				}
				return nodes;
			} 
			catch(Exception ex)
			{
				throw new Exception (ex.Message);
			}
			finally
			{
				ServiceLocator.Instance.Release(definitionComponent);
			}
		}

		[Transaction(TransactionMode.Requires)]
		public ProcessStateEnum CheckSubState( int projectID,string flowStep)
		{			
//			flowStep = flowStep.Trim();
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			ProcessStateList states = (ProcessStateList)Configuration.ProcessDefinition.Clone();
//
//			ProcessStateEnum retVal = ProcessStateEnum.Default;
//
//			if (projectID != 0)
//			{
//				using(ISession session = sessionManager.OpenSession())
//				{
//					try
//					{
//						Project project = context.GetProject(session, projectID);						
//
//						if( flowStep == project.ProjectStatus ) return ProcessStateEnum.OnGoing;
//
//						//Do Set Current States
//						bool is_done = false;
//						int match_i=0, match_j=0;
//
//						for(int i=0; i<states.Count; i++)
//						{
//							ProcessState state = states[i];
//							for(int j=0; j<state.ChildrenStates.Count; j++)
//							{
//								if( state.ChildrenStates[j].Key == project.ProjectStatus )
//								{
//									is_done = true; //find the current status
//								}
//								if( state.ChildrenStates[j].Key == flowStep ) 
//								{
//									match_i = i;
//									match_j = j;
//									break;
//								}
//							}
//						}						
//
//						//find the state
//						if( match_j>=0 )
//						{
//							if (is_done)
//							{
//								retVal = ProcessStateEnum.Finished;
//							}
//							else
//							{
//								retVal = ProcessStateEnum.Default;
//							}
//							//Do Processs Tailor
//							ProjectTailor tailor = context.GetTailorConditions(session, project);
//							if( match_i == IQ_Index )
//							{
//								if ( (tailor&ProjectTailor.IsIQ) == ProjectTailor.None)
//								{
//									retVal = ProcessStateEnum.Tailored;
//								}
//									//=========*BSS*=============
//								else if( (tailor&ProjectTailor.IsBSS) == ProjectTailor.IsBSS)
//								{
//									//remove some nodes of IQ flow		
//									if( match_j== IQReviewRpt_SubIndex 
//										|| match_j==IQSumRpt_SubIndex
//										|| match_j==IQTestRV_SubIndex
//										|| match_j== IQTest_SubIndex
//										|| match_j== IQAsseRV_SubIndex
//										|| match_j== IQAsse_SubIndex
//										)
//										retVal = ProcessStateEnum.Tailored;
//									//=========End of BSS========
//								}
//							}
//
//							if( match_i == TQ_Index )
//							{
//								if ( (tailor&ProjectTailor.IsTQ) == ProjectTailor.None)
//								{
//									retVal = ProcessStateEnum.Tailored;
//								}
//								else
//								{
//									//tmp-2007-03-02
//									if( (tailor&ProjectTailor.IsSkipTQApprove)== ProjectTailor.IsSkipTQApprove)
//									{
//										if( match_j<=9 && match_j>=2 || match_j == 0 )
//											retVal = ProcessStateEnum.Tailored;
//									}
//								}
//							}
//
//							if( match_i == VP_Index )
//							{
//								if ( (tailor&ProjectTailor.IsVP) == ProjectTailor.None)
//								{
//									if( match_j == VP_SubIndex )  
//										retVal = ProcessStateEnum.Tailored;
//								}
//							}
//						}
//
//					}
//					finally
//					{
//						if (session != null)
//							session.Close();
//					}					
//				}
//			}			
//			return retVal;

			return ProcessStateEnum.OnGoing;
		}


		[Transaction(TransactionMode.Requires)]
		public ProcessStateEnum CheckState( int projectID, string flowPhase)
		{			
//			flowPhase = flowPhase.Trim();
//			if (!Configuration.IsSetStates)
//			{
//				this.SetProcessState();
//			}
//			ProcessStateList states = (ProcessStateList)Configuration.ProcessDefinition.Clone();
//
//			ProcessStateEnum retVal = ProcessStateEnum.Default;
//
//			if (projectID != 0)
//			{
//				using(ISession session = sessionManager.OpenSession())
//				{
//					try
//					{
//						Project project = context.GetProject(session, projectID);
//
//						//Do Set Current States
//						bool is_done = false;
//						int match_i=0;
//
//						for(int i=0; i<states.Count; i++)
//						{
//							ProcessState state = states[i];
//
//							for(int j=0; j<state.ChildrenStates.Count; j++)
//							{
//								if( state.ChildrenStates[j].Key == project.ProjectStatus )
//								{
//									//is ongoing, return
//									if( state.Key == flowPhase ) return ProcessStateEnum.OnGoing;
//
//									is_done = true; //find the current status
//									break;
//								}
//							}
//
//							if( state.Key == flowPhase) 
//							{
//								match_i = i;
//								break;
//							}
//
//						}						
//
//						//find the state
//						if( match_i>=0 )
//						{
//							if (is_done)
//							{
//								retVal = ProcessStateEnum.Default;
//							}
//							else
//							{
//								retVal = ProcessStateEnum.Finished;
//							}
//
//							//Do Processs Tailor
//							ProjectTailor tailor = context.GetTailorConditions(session, project);
//							if( match_i == IQ_Index )
//							{
//								if ( (tailor&ProjectTailor.IsIQ) == ProjectTailor.None)
//								{
//									retVal = ProcessStateEnum.Tailored;
//								}		
//							}
//
//							if( match_i == TQ_Index )
//							{
//								if ( (tailor&ProjectTailor.IsTQ) == ProjectTailor.None)
//								{
//									retVal = ProcessStateEnum.Tailored;
//								}	
//							}
//						}
//
//
//					}
//					finally
//					{
//						session.Clear();
//						session.Close();
//					}					
//				}
//			}			
//			return retVal;

			return ProcessStateEnum.OnGoing;
		}


		[Transaction(TransactionMode.Requires)]
		public string GetRoleByActivityState(long processDefinitionId, string activityStateName)
		{
			Hashtable nodes = this.GetNodes(processDefinitionId);
			foreach (object node in nodes.Values)
			{
				NetBpm.Workflow.Definition.Impl.ActivityStateImpl activityState = node as NetBpm.Workflow.Definition.Impl.ActivityStateImpl;
				if (activityState != null)
				{
					if (activityState.Name != activityStateName) continue;

					System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
					xmlDoc.LoadXml(activityState.AssignmentDelegation.Configuration);
					System.Xml.XmlNode xmlNode = xmlDoc.SelectSingleNode("cfg/parameter[@name=\"role\"]");
					if (xmlNode != null) return xmlNode.InnerText;
				}
			}
			return null;
		}
	}
}
